package channel

import (
	"fmt"
	"time"
)

func Communication() {
	// 定义可读可写的通道，没有缓冲，必须写一个就要立马读出来一个才能继续使用
	//ch := make(chan int, 0)
	//go communicationF1(ch)
	//go communicationF2(ch)
}

// 接收一个只写通道
func communicationF1(ch chan<- int) {
	// 给通道内写入0-99
	for i := 0; i < 100; i++ {
		ch <- i
	}
}

// 接收一个只读通道
func communicationF2(ch <-chan int) {
	// 读取通道内所有数据
	for i := range ch {
		fmt.Println(i)
	}
}

// 并发场景下同步机制
func ConcurrentSync() {
	// 带缓冲的通道
	ch := make(chan int, 10) // 10个缓冲
	// 两个协程写入数据
	go func() {
		for i := 0; i < 100; i++ {
			ch <- i
		}
	}()
	go func() {
		for i := 0; i < 100; i++ {
			ch <- i
		}
	}()
	// 读取消息
	go func() {
		for i := range ch {
			fmt.Println(i)
		}
	}()
}

// 协程退出和多路复用
func NoticeAndMultipType() {
	// 不同类型的通道
	ch := make(chan int, 0)
	strCh := make(chan string, 0)
	done := make(chan struct{}, 0) // 多路复用
	go noticeMutipInt(ch)
	go noticeMutipString(strCh)
	go noticeMutip(ch, strCh, done)
	time.Sleep(5 * time.Second)
	close(done) // 关闭通道时候，会想所有关联的子协程发送临值
}
func noticeMutipInt(ch chan<- int) {
	for i := 0; i < 100; i++ {
		ch <- i
	}
}
func noticeMutipString(ch chan<- string) {
	for i := 0; i < 100; i++ {
		ch <- "abc"
	}
}
func noticeMutip(ch <-chan int, strCh <-chan string, done <-chan struct{}) {
	a := 0
	for {
		select {
		case i := <-ch:
			fmt.Println("数字：", i)
		case str := <-strCh:
			fmt.Println("字符串：", str)
		case <-done:
			fmt.Println("收到退出通知")
			return
			//	死循环中根据实际场景看要不要写defaault，会一直循环
		}
		a += 1
		fmt.Println("累计执行次数：", a)
	}

}
